package com.xudm.cdg.aspect;


import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.xudm.cdg.entity.system.OperationLog;
import com.xudm.cdg.mapper.system.OperationLogMapper;
import com.xudm.cdg.service.system.IOperationLogService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.Arrays;

/**
 * @author xudm
 */
//@Aspect
//@Component
public class LogAspect {

    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
    private final IOperationLogService operationLogService;

    public LogAspect(IOperationLogService operationLogService) {
        this.operationLogService = operationLogService;
    }

    @Pointcut("execution(public * com.xudm.cdg.controller..*(..))")
    public void logPointCut() {
    }

    /**
     * 环绕通知
     *
     * @param joinPoint 切入点
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = null;
        long start = System.currentTimeMillis();
        try {
            // 执行方法
            result = joinPoint.proceed();

        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        }
        long end = System.currentTimeMillis();
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();

            String args = Arrays.toString(joinPoint.getArgs());
            // 获取切入点所在的方法
            String methodName = signature.getMethod().getName();
            // 获取请求的类名
            String className = joinPoint.getTarget().getClass().getSimpleName();

            String moduleName = className + "#" + methodName;

            // 获取RequestAttributes
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            // 从获取RequestAttributes中获取HttpServletRequest的信息
            HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);

            OperationLog optionalLong = createOperationLog(request, moduleName, args, result);
            optionalLong.setCostTime(end - start);
            operationLogService.save(optionalLong);
        } catch (Exception e) {
            log.error("记录日志异常", e);
        }
        return result;
    }

    private OperationLog createOperationLog(HttpServletRequest request, String moduleName, String args, Object result) {
        OperationLog operationLog = new OperationLog();
        operationLog.setVisitModule(moduleName);
        operationLog.setRequestUrl(request.getRequestURI());
        operationLog.setRequestType(request.getMethod());
        String localAddr = request.getLocalAddr();
        int localPort = request.getLocalPort();
        operationLog.setServerIp(localAddr + ":" + localPort);
        operationLog.setClientIp(request.getRemoteAddr());
        operationLog.setRequestHeader(getHreaders(request));
        operationLog.setInputParams(args);
        operationLog.setOutputParams(JSON.toJSONString(result));
        return operationLog;
    }

    private String getHreaders(HttpServletRequest request) {
        StringBuilder sb = new StringBuilder();
        request.getHeaderNames().asIterator().forEachRemaining(name -> {
            sb.append(name).append(":").append(request.getHeader(name)).append(";");
        });
        return sb.toString();
    }

}
